package com.gupao.javavip.dubbo.rpc.serialize.messagepack;

import lombok.extern.apachecommons.CommonsLog;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.msgpack.MessagePack;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.HashMap;

/**
 * Messagepack object input implementation
 */
@CommonsLog
public class MessagepackObjectInput implements ObjectInput {

    private final DataInputStream dis;
    private final MessagePack messagePack;

    public MessagepackObjectInput(InputStream inputStream) {
        this.messagePack = new MessagePack();
        this.dis = new DataInputStream(inputStream);
    }


    @SuppressWarnings("ResultOfMethodCallIgnored")
    @Override
    public Object readObject() throws IOException, ClassNotFoundException {
        try {
            int classNameLength = dis.readInt();
            int bytesLength = dis.readInt();

            if (classNameLength <= 0 || bytesLength <= 0) {
                throw new IOException();
            }

            byte[] classNameBytes = new byte[classNameLength];
            dis.readFully(classNameBytes, 0, classNameLength);

            byte[] bytes = new byte[bytesLength];
            dis.readFully(bytes, 0, bytesLength);

            String className = new String(classNameBytes);
            Class clazz = Class.forName(className);

            if (log.isDebugEnabled()) {
//                log.debug("messagePack decode...");
//                log.debug("className:" + className + ",   classNameBytes.length:" + classNameBytes.length);
//                log.debug("bytes.length:" + bytesLength);
            }

            //TODO  HashMap 需要做特殊处理，待优化
            if (clazz.isAssignableFrom(HashMap.class)) {
//                Template<Map<String, String>> mapTmpl = tMap(TString, TString);
//                return messagePack.read(bytes,mapTmpl);

                return messagePack.read(bytes, ObjectTemplate.tObject());
            }

            return messagePack.read(bytes, clazz);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new IOException(e);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T readObject(Class<T> clazz) throws IOException, ClassNotFoundException {
        return (T) readObject();
    }

    @Override
    public <T> T readObject(Class<T> cls, Type type) throws IOException, ClassNotFoundException {
        return readObject(cls);
    }

    @Override
    public boolean readBool() throws IOException {
        return dis.readBoolean();
    }

    @Override
    public byte readByte() throws IOException {
        return dis.readByte();
    }

    @Override
    public short readShort() throws IOException {
        return dis.readShort();
    }

    @Override
    public int readInt() throws IOException {
        return dis.readInt();
    }

    @Override
    public long readLong() throws IOException {
        return dis.readLong();
    }

    @Override
    public float readFloat() throws IOException {
        return dis.readFloat();
    }

    @Override
    public double readDouble() throws IOException {
        return dis.readDouble();
    }

    @Override
    public String readUTF() throws IOException {
        int length = dis.readInt();
        byte[] bytes = new byte[length];
        dis.read(bytes, 0, length);
        return new String(bytes);
    }

    @Override
    public byte[] readBytes() throws IOException {
        int length = dis.readInt();
        byte[] bytes = new byte[length];
        dis.read(bytes, 0, length);
        return bytes;
    }
}
